package com.cgs.query.domain

import com.cgs.query.util.EnumUtils
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import org.hibernate.annotations.GenericGenerator
import java.sql.JDBCType
import javax.persistence.*

@Entity
@ApiModel("Query定义")
@Table(name = "query_define")
@JsonIgnoreProperties(ignoreUnknown = true)
class QueryDefine() : BaseDomain() {

    @Id
    @ApiModelProperty("编号")
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    @GeneratedValue(generator = "idGenerator")
    var id: String = ""
    @Column
    @ApiModelProperty("名称")
    var name: String = ""
    @Column
    @ApiModelProperty("说明")
    var explainStr: String = ""
    @Column
    @ElementCollection
    @CollectionTable(name = "query_define_tag")
    @ApiModelProperty("标签数组")
    var tags: List<String> = mutableListOf()

    constructor(id: String) : this() {
        this.id = id
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is QueryDefine) return false

        if (id != other.id) return false

        return true
    }

    override fun hashCode(): Int {
        return id.hashCode()
    }

}


@Entity
@ApiModel("定义执行对象")
@Table(name = "query_define_execution")
@JsonIgnoreProperties(ignoreUnknown = true)
class ExecutionObj() : BaseDomain() {

    @Id
    @ApiModelProperty("编号")
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    @GeneratedValue(generator = "idGenerator")
    var id: String = ""
    @Column
    @ApiModelProperty("定义编号")
    var defineId: String = ""
    @Column
    @ApiModelProperty("版本号")
    var version: String = ""
    @Lob
    @Column
    @ApiModelProperty("字符串sql")
    var statement: String = ""
    @Column
    @ApiModelProperty("声明类型")
    var statementType = StatementType.PREPARED.name
    @Column
    @ApiModelProperty("渲染方式")
    var renderType = RenderType.QUESTION_MARK.name
    @Column
    @ApiModelProperty("预览参数")
    var previewParams: String? = ""
    @Column
    @ApiModelProperty("索引信息")
    var indexInfo: String? = ""
    @Column
    @ApiModelProperty("优化方向")
    var betterInfo: String? = ""
    @Column
    @ApiModelProperty("扩展参数")
    var extendsJson: String? = ""

    constructor(id: String) : this() {
        this.id = id
    }
}


/**ִ构建完成后的sql语句包装*/
class BoundSql(sql: String, parameterMappings: List<ParameterMapping>) {
    var sql = sql
    var parameterMappings = parameterMappings

    override fun toString(): String {
        return "Sql:[$sql] , parameterMappings:[$parameterMappings]"
    }

}

/**参数映射*/
class ParameterMapping(var property: String, value: Any) {

    var value = value

    var mode = ParameterMode.IN

    var jdbcType = JDBCType.JAVA_OBJECT

    override fun toString(): String {
        return "ParameterMapping(property='$property', value=$value, mode=$mode, jdbcType=$jdbcType)"
    }
}

/**参数类型*/
enum class ParameterMode {
    IN, OUT, INOUT;
}


/**解析一个querydefine*/
class MappedStatement {

    val statementType: StatementType

    val executionObj: ExecutionObj

    val source: QuerySource

    var projectName: String? = null

    var wholeName: String? = null

    var limit: Int? = null

    constructor(projectName: String, wholeName: String, source: QuerySource, executionObj: ExecutionObj) {
        this.executionObj = executionObj
        this.statementType = EnumUtils.valueOf(StatementType::class.java, executionObj.statementType)
        this.wholeName = wholeName
        this.source = source
        this.projectName = projectName
    }

    constructor(source: QuerySource, executionObj: ExecutionObj) {
        this.executionObj = executionObj
        this.statementType = EnumUtils.valueOf(StatementType::class.java, executionObj.statementType)
        this.source = source
    }

}

/**声明类型*/
enum class StatementType {
    STATEMENT, PREPARED, CALLABLE, SCRIPT, PAGINATION;
}

/**数据库操作类型*/
enum class SqlCommandType {
    QUERY, UPDATE;
}

/**渲染方式*/
enum class RenderType {
    /**不需要渲染*/
    NO,
    /**mybatis渲染*/
    MYBATIS,
    /**?渲染*/
    QUESTION_MARK,
    /**freemarker渲染*/
    FREEMARKER
}